﻿using EFFC.Frame.Net.Module.Extend.EWRA.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EFFC.Extends.LinqDLR2SQL;
using EFFC.Frame.Net.Unit.DB;
using EFFC.Frame.Net.Base.Data.Base;
using EFFC.Frame.Net.Module.Extend.EWRA.Attributes.Validation;
using EFFC.Frame.Net.Base.Common;
using EFFC.Frame.Net.Base.Data;
using EFFC.Frame.Net.Module.Business.Datas;
using ICPFrameLib.Business;
using ICPFrameLib.Attributes;
using EFFC.Frame.Net.Unit.DB.Parameters;
using ICPFrameLib.Common;
using System.IO;
using EFFC.Frame.Net.Base.Constants;

namespace XHRPMIS.Business.v1._0
{
      public class ICPDataSet : MyRestLogic
{
    [ActionAuth("DataSet")]
    [EWRARoute("get", "/icpdataset")]
    [EWRARouteDesc("获取数据集列表")]
    [EWRAAddInput("limit", "int", "每页笔数，当mode为Normal时需要提供", "默认为10", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAAddInput("page", "int", "指定页数，当mode为Normal时需要提供", "默认为1", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAAddInput("filter", "string", "过滤条件", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
data:{
TotalRow:'总笔数',
CurrentPage:'当前页数',
TotalPage:'总页数',
Count_Of_OnePage:'每页笔数',
data:[{
uid:'资料PK',
title:'名称',
source_uid:'数据源UID',
source_name:'数据源名称',
target:'目标table名称',
joins:'join表的名称，多个逗号分隔',
join_express:'join表达式',
dimension:'维度表达式',
dimension_title:'维度名称',
measurement:'量度表达式',
measurement_title:'量度名称',
filter_express:'过滤表达式'
bi_express:'完整表达式',
is_test_success:'是否测试成功',
is_active:'是否启用',
parameters:[参数定义列表]
}
}")]
    object GetList()
    {
        SetCacheEnable(false);
        var filter = ComFunc.nvl(QueryStringD.filter);
        var metaup = DB.NewMetaUnitParameter();

        var re = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET", "a")
                  join t2 in DB.LamdaTable(metaup, "EXTEND_DATASOURCE", "b").LeftJoin() on t.SourceUID equals t2.SourceUID
                  where t.notnull(filter, t.Title.contains(filter) || t.Target.contains(filter))
                  select new
                  {
                      uid = t.SetUID,
                      title = t.Title,
                      source_uid = t.SourceUID,
                      source_name = t2.SourceName,
                      target = t.Target,
                      joins = t.JoinTarget,
                      join_express = t.JoinExpress,
                      dimension = t.Dimension,
                      dimension_title = t.DimensionTitle,
                      measurement = t.Measurement,
                      measurement_title = t.MeasurementTitle,
                      filter_express = t.FilterExpress,
                      bi_express = t.BIExpress,
                      is_test_success = t.IsTestSuccess,
                      is_active = t.IsActive
                  }).QueryByPage(metaup, "Title");
        var list = re.QueryData<FrameDLRObject>().Select(d =>
        {
            var parameters = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET_PARAMETERS", "a")
                              where t.SetUID == d.GetValue("uid")
                              select new
                              {
                                  uid = t.UID,
                                  param_name = t.ParameterName,
                                  source = t.Source,
                                  table = t.TableName,
                                  express = t.Express
                              }).GetQueryList(metaup);
            var expobj = BIParametersExpress.Parse("[" + string.Join(",", parameters.Select(d => ComFunc.nvl(d.GetValue("express")))) + "]").Result;
            if (expobj != null)
            {
                foreach (var p in parameters)
                {
                    var obj = expobj.Parameters.Where(w => w.ParameterName == ComFunc.nvl(p.GetValue("param_name"))).First();
                    p.SetValue("as", obj.As);
                    p.SetValue("join", obj.OriJoinExpress);
                    p.SetValue("action", obj.Action);
                    p.SetValue("column", obj.Column);
                    p.SetValue("filter", obj.OriWhereExpress);
                    p.SetValue("group", obj.GroupExpress);
                    p.Remove("express");
                }
            }
            d.SetValue("parameters", parameters);
            return d;
        }).ToList();

        return ResultHelper.DFormQueryByPageFormat(re.Count_Of_OnePage, re.CurrentPage, re.TotalPage, re.TotalRow, list);
    }
    [ActionAuth("DataSet")]
    [EWRAEmptyValid("title")]
    [EWRARouteDesc("新增一个默认启用的数据集")]
    [EWRAAddInput("title", "string", "名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAAddInput("source_uid", "string", "数据源UID", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("parameters", "string", @"参数集，先UrlCode再采用Base64编码,格式如下：[{
'source':'数据源名称，如果为元数据表，则不填或填入：_meta_',
'table':'表名',
'as':'别名',
'join':'Join表达式，符合DBExpress中的$table中join部分($table中的table2开始部分，table1为table中指定的)',
'param_name':'变量名称',
'action':'操作指令:max-最大值,min-最小值,avg-平均值,abs-绝对值',
'column':'待操作的栏位名称',
'filter':'过滤表达式，符合DBExpress中的$where表达式',
'group':'分组表达式，符合DBExpress中的$groupby表达式'
}]", "无默认值 ", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("bi_express", "string", @"BI表达式，先UrlCode再采用Base64编码,格式如下：{
id:""指定的table名称"",
as:""别名"",
join:'Join表达式，符合DBExpress中的$table中join部分',
dimension:{
  '{key}':'维度表达式,维度被用于分组识别，比如：年度、季度等,符合DBExpress中的column的表达式'
},
dimension_titile:{
  '{key}':'名称'
},
measurement:{
    '{key}':'量度度表达式,量度属于统计的显示结果，如：sum,count,max,min等，符合DBExpress中的column的表达式'
},
measurement_title:{
    '{key}':'名称'
},
'where':'条件表达式，符合DBExpress中的where表达式',
'orderby':'排序表达式,使用维度中的key，多个用逗号分隔，格式:{key1} [asc|desc],{key2} [asc|desc],...'
}", "无默认值 ", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息"",
uid:""成功时候返回的UID""
}")]
    public override object post()
    {
        var title = ComFunc.nvl(PostDataD.title);
        var source_uid = ComFunc.nvl(PostDataD.source_uid);
        string bi_express = ComFunc.UrlDecode(ComFunc.IsBase64Then(ComFunc.nvl(PostDataD.bi_express)));
        string parameters = ComFunc.UrlDecode(ComFunc.IsBase64Then(ComFunc.nvl(PostDataD.parameters)));
        if (bi_express == "")
        {
            return new
            {
                code = "failed",
                msg = "表达式格式不正确"
            };
        }
        BIParametersExpress pobj = null;
        if (parameters != "")
        {
            var bpresult = BIParametersExpress.Parse(parameters);
            if (!bpresult.IsSuccess)
            {
                return new
                {
                    code = "failed",
                    msg = $"参数集表达式不正确:{bpresult.Msg}"
                };
            }
            pobj = bpresult.Result;
        }
        var uid = Guid.NewGuid().ToString();
        var metaup = DB.NewMetaUnitParameter();
        BeginTrans();
        if ((from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET", "a")
             where t.Title == title
             select t).IsExists(metaup))
        {
            return new
            {
                code = "failed",
                msg = "名称重复"
            };
        }
        var context = GetBIParameters(pobj, metaup);
        var re = BIExpress.Parse(bi_express, null, context);
        if (!re.IsSuccess)
        {
            return new
            {
                code = "failed",
                msg = re.Msg
            };
        }
        var msg = "";
        if (!TestExpress(re.Result, metaup, source_uid, ref msg))
        {
            return new
            {
                code = "failed",
                msg = $"表达式测试失败:{msg}"
            };
        }
        DB.QuickInsert(metaup, "EXTEND_BI_DATASET", new
        {
            SetUID = uid,
            Title = title,
            SourceUID = source_uid,
            Target = re.Result.Target,
            JoinTarget = string.Join(",", re.Result.Join.Select(d => d.Target)),
            JoinExpress = re.Result.JoinExpress.ToJSONString(false),
            Dimension = string.Join(",", re.Result.Dimension.Select(d => $"{d.Key}:{d.Express}")),
            Measurement = string.Join(",", re.Result.Measurement.Select(d => $"{d.Key}:{d.Express}")),
            DimensionTitle = string.Join(",", re.Result.Dimension.Select(d => $"{d.Key}:{d.Title}")),
            MeasurementTitle = string.Join(",", re.Result.Measurement.Select(d => $"{d.Key}:{d.Title}")),
            FilterExpress = re.Result.Where.ToJSONString(false),
            BIExpress = bi_express,
            IsTestSuccess = 1,
            IsActive = 1,
            add_id = TokenPayLoad.ID,
            add_name = ComFunc.nvl(TokenPayLoad["name"]),
            add_ip = ClientInfo.IP,
            add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
        });
        if (pobj != null)
        {
            foreach (var p in pobj.Parameters)
            {
                DB.QuickInsert(metaup, "EXTEND_BI_DATASET_PARAMETERS", new
                {
                    SetUID = uid,
                    UID = Guid.NewGuid().ToString(),
                    ParameterName = p.ParameterName,
                    Source = p.DataSource,
                    TableName = p.TableName,
                    Express = p.OriExpress,
                    add_id = TokenPayLoad.ID,
                    add_name = ComFunc.nvl(TokenPayLoad["name"]),
                    add_ip = ClientInfo.IP,
                    add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                });
            }
        }

        CommitTrans();
        return new
        {
            code = "success",
            msg = "操作成功",
            uid
        };
    }
    [ActionAuth("DataSet")]
    [EWRAEmptyValid("title")]
    [EWRARouteDesc("修改一个数据集")]
    [EWRAAddInput("id", "string", "资料PK", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("title", "string", "名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAAddInput("source_uid", "string", "数据源UID", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("parameters", "string", @"参数集，先UrlCode再采用Base64编码,格式如下：[{
'source':'数据源名称，如果为元数据表，则不填或填入：_meta_',
'table':'表名',
'as':'别名',
'join':'Join表达式，符合DBExpress中的$table中join部分($table中的table2开始部分，table1为table中指定的)',
'param_name':'变量名称',
'action':'操作指令:max-最大值,min-最小值,avg-平均值,abs-绝对值',
'column':'待操作的栏位名称',
'filter':'过滤表达式，符合DBExpress中的$where表达式',
'group':'分组表达式，符合DBExpress中的$groupby表达式'
}]", "无默认值 ", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("bi_express", "string", @"BI表达式，先UrlCode再采用Base64编码,格式如下：{
id:""指定的table名称"",
as:""别名"",
join:'Join表达式，符合DBExpress中的$table中join部分',
dimension:{
  '{key}':'维度表达式,维度被用于分组识别，比如：年度、季度等,符合DBExpress中的column的表达式'
},
dimension_titile:{
  '{key}':'名称'
},
measurement:{
    '{key}':'量度度表达式,量度属于统计的显示结果，如：sum,count,max,min等，符合DBExpress中的column的表达式'
},
measurement_title:{
    '{key}':'名称'
},
'where':'条件表达式，符合DBExpress中的where表达式',
'orderby':'排序表达式,使用维度中的key，多个用逗号分隔，格式:{key1} [asc|desc],{key2} [asc|desc],...'
}", "无默认值 ", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息""
}")]
    public override object patch(string id)
    {
        var title = ComFunc.nvl(PostDataD.title);
        var source_uid = ComFunc.nvl(PostDataD.source_uid);
        string bi_express = ComFunc.UrlDecode(ComFunc.IsBase64Then(ComFunc.nvl(PostDataD.bi_express)));
        string parameters = ComFunc.UrlDecode(ComFunc.IsBase64Then(ComFunc.nvl(PostDataD.parameters)));
        if (bi_express == "")
        {
            return new
            {
                code = "failed",
                msg = "表达式格式不正确"
            };
        }
        BIParametersExpress pobj = null;
        if (parameters != "")
        {
            var bpresult = BIParametersExpress.Parse(parameters);
            if (!bpresult.IsSuccess)
            {
                return new
                {
                    code = "failed",
                    msg = $"参数集表达式不正确:{bpresult.Msg}"
                };
            }
            pobj = bpresult.Result;
        }
        var metaup = DB.NewMetaUnitParameter();
        BeginTrans();
        dynamic info = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET", "a")
                        where t.SetUID == id
                        select t).GetQueryList(metaup).FirstOrDefault();
        if (info == null)
        {
            return new
            {
                code = "failed",
                msg = "无该资料"
            };
        }

        if ((from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET", "a")
             where t.Title == title && t.SetUID != id
             select t).IsExists(metaup))
        {
            return new
            {
                code = "failed",
                msg = "名称重复"
            };
        }
        var re = BIExpress.Parse(bi_express, null, GetBIParameters(pobj, metaup));
        if (!re.IsSuccess)
        {
            return new
            {
                code = "failed",
                msg = re.Msg
            };
        }
        var msg = "";
        if (!TestExpress(re.Result, metaup, source_uid, ref msg))
        {
            return new
            {
                code = "failed",
                msg = $"表达式测试失败:{msg}"
            };
        }
        DB.QuickUpdate(metaup, "EXTEND_BI_DATASET", new
        {
            Title = title,
            SourceUID = source_uid,
            Target = re.Result.Target,
            JoinTarget = string.Join(",", re.Result.Join.Select(d => d.Target)),
            JoinExpress = re.Result.JoinExpress.ToJSONString(false),
            Dimension = string.Join(",", re.Result.Dimension.Select(d => $"{d.Key}:{d.Express}")),
            Measurement = string.Join(",", re.Result.Measurement.Select(d => $"{d.Key}:{d.Express}")),
            DimensionTitle = string.Join(",", re.Result.Dimension.Select(d => $"{d.Key}:{d.Title}")),
            MeasurementTitle = string.Join(",", re.Result.Measurement.Select(d => $"{d.Key}:{d.Title}")),
            FilterExpress = re.Result.Where.ToJSONString(false),
            BIExpress = bi_express,
            IsTestSuccess = 1,
            last_id = TokenPayLoad.ID,
            last_name = ComFunc.nvl(TokenPayLoad["name"]),
            last_ip = ClientInfo.IP,
            last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
        }, new
        {
            info.SetUID
        });
        DB.QuickDelete(metaup, "EXTEND_BI_DATASET_PARAMETERS", new
        {
            SetUID = info.SetUID
        });
        if (pobj != null)
        {
            foreach (var p in pobj.Parameters)
            {
                DB.QuickInsert(metaup, "EXTEND_BI_DATASET_PARAMETERS", new
                {
                    SetUID = info.SetUID,
                    UID = Guid.NewGuid().ToString(),
                    ParameterName = p.ParameterName,
                    Source = p.DataSource,
                    TableName = p.TableName,
                    Express = p.OriExpress,
                    add_id = TokenPayLoad.ID,
                    add_name = ComFunc.nvl(TokenPayLoad["name"]),
                    add_ip = ClientInfo.IP,
                    add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                });
            }
        }

        CommitTrans();
        return new
        {
            code = "success",
            msg = "操作成功"
        };
    }
    [ActionAuth("DataSet")]
    [EWRARouteDesc("删除一个数据源")]
    [EWRAAddInput("id", "string", "UID", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAOutputDesc("返回结果", @"根据http的状态码来识别，204标识操作成功，404表示操作识别未找到删除的资料")]
    public override bool delete(string id)
    {
        var metaup = DB.NewMetaUnitParameter();
        BeginTrans();
        dynamic info = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET", "a")
                        where t.SetUID == id
                        select t).GetQueryList(metaup).FirstOrDefault();
        if (info == null)
        {
            return false;
        }
        DB.QuickDelete(metaup, "EXTEND_BI_DATASET_PARAMETERS", new
        {
            SetUID = info.SetUID
        });
        DB.QuickDelete(metaup, "EXTEND_BI_DATASET", new
        {
            info.SetUID
        });
        CommitTrans();
        return true;
    }
    [ActionAuth("DataSet")]
    [EWRARoute("patch", "/icpdataset/{id}/active")]
    [EWRARouteDesc("启用指定的数据源")]
    [EWRAAddInput("id", "string", "资料pk", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息""
}")]
    public object Active(string id)
    {
        var metaup = DB.NewMetaUnitParameter();
        BeginTrans();
        dynamic info = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET", "a")
                        where t.SetUID == id
                        select t).GetQueryList(metaup).FirstOrDefault();
        if (info == null)
        {
            return new
            {
                code = "failed",
                msg = "无该资料"
            };
        }
        if (BoolStd.IsNotBoolThen(info.IsActive))
        {
            return new
            {
                code = "failed",
                msg = "该数据集已启用"
            };
        }
        DB.QuickUpdate(metaup, "EXTEND_BI_DATASET", new
        {
            IsActive = 1,
            last_id = TokenPayLoad.ID,
            last_name = ComFunc.nvl(TokenPayLoad["name"]),
            last_ip = ClientInfo.IP,
            last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
        }, new
        {
            info.SetUID
        });
        CommitTrans();

        return new
        {
            code = "success",
            msg = "操作成功"
        };
    }
    [ActionAuth("DataSet")]
    [EWRARoute("patch", "/icpdataset/{id}/deactive")]
    [EWRARouteDesc("停用指定的数据源")]
    [EWRAAddInput("id", "string", "资料pk", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息""
}")]
    public object Deactive(string id)
    {
        var metaup = DB.NewMetaUnitParameter();
        BeginTrans();
        dynamic info = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET", "a")
                        where t.SetUID == id
                        select t).GetQueryList(metaup).FirstOrDefault();
        if (info == null)
        {
            return new
            {
                code = "failed",
                msg = "无该资料"
            };
        }
        if (!BoolStd.IsNotBoolThen(info.IsActive))
        {
            return new
            {
                code = "failed",
                msg = "该数据集已停用"
            };
        }
        DB.QuickUpdate(metaup, "EXTEND_BI_DATASET", new
        {
            IsActive = 0,
            last_id = TokenPayLoad.ID,
            last_name = ComFunc.nvl(TokenPayLoad["name"]),
            last_ip = ClientInfo.IP,
            last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
        }, new
        {
            info.SetUID
        });
        CommitTrans();

        return new
        {
            code = "success",
            msg = "操作成功"
        };
    }
    [ActionAuth("DataSet")]
    [EWRARoute("post", "/data_set/test_express")]
    [EWRARouteDesc("测试BI表达式是否有效")]
    [EWRAEmptyValid("bi_express")]
    [EWRAAddInput("source_uid", "string", "数据源UID,如果为空则表示为元数据", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("parameters", "string", @"参数集，先UrlCode再采用Base64编码,格式如下：[{
'source':'数据源名称，如果为元数据表，则不填或填入：_meta_',
'table':'表名',
'as':'别名',
'join':'Join表达式，符合DBExpress中的$table中join部分($table中的table2开始部分，table1为table中指定的)',
'param_name':'变量名称',
'action':'操作指令:max-最大值,min-最小值,avg-平均值,abs-绝对值',
'column':'待操作的栏位名称',
'filter':'过滤表达式，符合DBExpress中的$where表达式',
'group':'分组表达式，符合DBExpress中的$groupby表达式'
}]", "无默认值 ", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("bi_express", "string", @"BI表达式，先UrlCode再采用Base64编码,格式如下：{
id:""指定的table名称"",
as:""别名"",
join:'Join表达式，符合DBExpress中的$table中join部分',
dimension:{
  '{key}':'维度表达式,维度被用于分组识别，比如：年度、季度等,符合DBExpress中的column的表达式'
},
dimension_titile:{
  '{key}':'名称'
},
measurement:{
    '{key}':'量度度表达式,量度属于统计的显示结果，如：sum,count,max,min等，符合DBExpress中的column的表达式'
},
measurement_title:{
    '{key}':'名称'
},
'where':'条件表达式，符合DBExpress中的where表达式',
'orderby':'排序表达式,使用维度中的key，多个用逗号分隔，格式:{key1} [asc|desc],{key2} [asc|desc],...'
}", "无默认值 ", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息""
}")]
    public object TestBIExpress()
    {
        var source_uid = ComFunc.nvl(PostDataD.source_uid);
        string bi_express = ComFunc.UrlDecode(ComFunc.IsBase64Then(ComFunc.nvl(PostDataD.bi_express)));
        string parameters = ComFunc.UrlDecode(ComFunc.IsBase64Then(ComFunc.nvl(PostDataD.parameters)));
        if (bi_express == "")
        {
            return new
            {
                code = "failed",
                msg = "表达式格式不正确"
            };
        }
        BIParametersExpress pobj = null;
        if (parameters != "")
        {
            var bpresult = BIParametersExpress.Parse(parameters);
            if (!bpresult.IsSuccess)
            {
                return new
                {
                    code = "failed",
                    msg = $"参数集表达式不正确:{bpresult.Msg}"
                };
            }
            pobj = bpresult.Result;
        }
        var metaup = DB.NewMetaUnitParameter();
        var context = GetBIParameters(pobj, metaup);
        var re = BIExpress.Parse(bi_express, null, context);
        if (!re.IsSuccess)
        {
            return new
            {
                code = "failed",
                msg = re.Msg
            };
        }

        var msg = "";
        if (!TestExpress(re.Result, metaup, source_uid, ref msg))
        {
            return new
            {
                code = "failed",
                msg = $"表达式测试失败:{msg}"
            };
        }
        else
        {
            return new
            {
                code = "success",
                msg = "测试通过"
            };
        }
    }
    [EWRARoute("get", "/data_set/bi_function/list")]
    [EWRARouteDesc("获取BIExpress中可用的Function列表")]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
data:[{
name:'名称',
format:'格式',
desc:'描述'
}]
}")]
    public object GetBIFunctionList()
    {
        SetCacheEnable(false);
        var metaup = DB.NewMetaUnitParameter();

        var re = (from t in DB.LamdaTable(metaup, "EXTEND_BIEXPRESSION_FUNCTION", "a")
                  orderby t.FunctionName
                  select new
                  {
                      name = t.FunctionName,
                      format = t.FunctionFormat,
                      desc = t.Desc
                  }).GetQueryList(metaup);

        return new
        {
            code = "success",
            msg = "",
            data = re
        };
    }
    [EWRARoute("get", "/data_set/activelist")]
    [EWRARouteDesc("获取启用的数据集")]
    [EWRAAddInput("filter", "string", "过滤条件", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
data:[{
uid:'资料PK',
title:'名称',
source_uid:'数据源UID',
source_name:'数据源名称',
target:'目标table名称',
joins:'join表的名称，多个逗号分隔',
join_express:'join表达式',
dimension:'维度表达式',
dimension_title:'维度名称',
measurement:'量度表达式',
measurement_title:'量度名称',
filter_express:'过滤表达式'
bi_express:'完整表达式',
is_test_success:'是否测试成功',
is_active:'是否启用'
}]
}")]
    public object GetActiveDataSet()
    {
        SetCacheEnable(false);
        var filter = ComFunc.nvl(QueryStringD.filter);
        var metaup = DB.NewMetaUnitParameter();

        var re = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET", "a")
                  join t2 in DB.LamdaTable(metaup, "EXTEND_DATASOURCE", "b").LeftJoin() on t.SourceUID equals t2.SourceUID
                  where t.notnull(filter, t.Title.contains(filter) || t.Target.contains(filter))
                  orderby t.title
                  select new
                  {
                      uid = t.SetUID,
                      title = t.Title,
                      source_uid = t.SourceUID,
                      source_name = t2.SourceName,
                      target = t.Target,
                      joins = t.JoinTarget,
                      join_express = t.JoinExpress,
                      dimension = t.Dimension,
                      dimension_title = t.DimensionTitle,
                      measurement = t.Measurement,
                      measurement_title = t.MeasurementTitle,
                      filter_express = t.FilterExpress,
                      bi_express = t.BIExpress,
                      is_test_success = t.IsTestSuccess,
                      is_active = t.IsActive
                  }).GetQueryList(metaup);

        return new
        {
            code = "success",
            msg = "",
            data = re
        };
    }
    [EWRARoute("post", "/data_set/{id}/excute")]
    [EWRARouteDesc("执行指定的数据集")]
    [EWRAAddInput("id", "string", "资料pk", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("include_sql_info", "bool", "返回的结果是否包含执行Sql信息", "默认false", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("limit", "int", "每页笔数，如果要查全部结果，请用1000等较大的值，为性能考虑尽量用较小的值", "默认为10", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAAddInput("page", "int", "指定页数", "默认为1", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAAddInput("other_filter", "string", "其它的条件表达式，符合DBExpress中的where表达式，json格式先UrlCode再采用base64编码", "默认false", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息"",
data:{
        Count_Of_OnePage:'每页笔数',
        CurrentPage: '当前页数',
        TotalPage:'总页数',
        TotalRow:'总笔数',
        QueryDatas:[数据集],
        CastMiSeconds:'执行SQL消耗的时间(毫秒)，include_sql_info为true时有效',
        ExcuteSql:'执行的SQL，include_sql_info为true时有效',
        ExcuteSqlParameters:'执行的参数，include_sql_info为true时有效'
    }
}")]
    public object RunDataSet(string id)
    {
        var include_sql_info = BoolStd.IsNotBoolThen(PostDataD.include_sql_info);
        string other_filter_str = ComFunc.UrlDecode(ComFunc.IsBase64Then(ComFunc.nvl(PostDataD.other_filter)));
        if (!FrameDLRObject.IsJson(other_filter_str))
        {
            return new
            {
                code = "failed",
                msg = "其它的条件表达式格式不正确"
            };
        }
        var metaup = DB.NewMetaUnitParameter();
        dynamic info = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET", "a")
                        where t.SetUID == id || t.Title == id
                        select t).GetQueryList(metaup).FirstOrDefault();
        if (info == null)
        {
            return new
            {
                code = "failed",
                msg = "无该资料"
            };
        }
        if (!BoolStd.IsNotBoolThen(info.IsActive))
        {
            return new
            {
                code = "failed",
                msg = "该数据集未启用，停止执行"
            };
        }
        var parameters = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET_PARAMETERS", "a")
                          where t.SetUID == info.SetUID
                          select t).GetQueryList(metaup).Select(d => ComFunc.nvl(d.GetValue("Express"))).ToList();
        var pexpress = BIParametersExpress.Parse(parameters);
        string biexpress = ComFunc.nvl(info.BIExpress);
        var re = BIExpress.Parse(biexpress, other_filter_str, GetBIParameters(pexpress.Result, metaup));
        if (!re.IsSuccess)
        {
            return new
            {
                code = "failed",
                msg = re.Msg
            };
        }
        var uc = ExcuteBIExpress(re.Result, metaup, ComFunc.nvl(info.SourceUID));
        return new
        {
            code = "success",
            msg = "",
            data = ResultHelper.DFormQueryByPageFormat(uc, include_sql_info)
        };
    }
    [EWRARoute("post", "/data_set/excute")]
    [EWRARouteDesc("执行指定的多个数据集")]
    [EWRAAddInput("ids", "string", "数据集PK或名称，多个用逗号分隔", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAAddInput("include_sql_info", "bool", "返回的结果是否包含执行Sql信息", "默认false", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("limit", "int", "每页笔数，如果要查全部结果，请用1000等较大的值，为性能考虑尽量用较小的值", "默认为10", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAAddInput("page", "int", "指定页数", "默认为1", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAAddInput("other_filters", "object", @"{
'数据集名称':'其它的条件表达式，符合DBExpress中的where表达式，json格式先UrlCode再采用base64编码'
}", "默认false", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAOutputDesc("返回结果", @"{
code:""success-成功，failed-失败"",
msg:""提示信息"",
data:{
    '{数据集名称}':{
            Count_Of_OnePage:'每页笔数',
            CurrentPage: '当前页数',
            TotalPage:'总页数',
            TotalRow:'总笔数',
            QueryDatas:[数据集],
            CastMiSeconds:'执行SQL消耗的时间(毫秒)，include_sql_info为true时有效',
            ExcuteSql:'执行的SQL，include_sql_info为true时有效',
            ExcuteSqlParameters:'执行的参数，include_sql_info为true时有效'
        }
    }
}")]
    public object RunDataSets()
    {
        string ids = ComFunc.nvl(PostDataD.ids);
        var include_sql_info = BoolStd.IsNotBoolThen(PostDataD.include_sql_info);
        FrameDLRObject other_filters = FrameDLRObject.CreateInstance(PostDataD.other_filters, FrameDLRFlags.SensitiveCase);
        foreach (var item in other_filters.Items)
        {
            var str = ComFunc.UrlDecode(ComFunc.IsBase64Then(ComFunc.nvl(PostDataD.other_filter)));
            if (!FrameDLRObject.IsJson(str))
            {
                return new
                {
                    code = "failed",
                    msg = "其它的条件表达式格式不正确"
                };
            }
        }


        var metaup = DB.NewMetaUnitParameter();
        var id_arr = ids.Split(",", StringSplitOptions.RemoveEmptyEntries);
        var list = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET", "a")
                    where t.SetUID.within(ids) || t.Title.within(ids)
                    select t).GetQueryList(metaup);
        if (list.Count <= 0)
        {
            return new
            {
                code = "failed",
                msg = "未查到数据集资料"
            };
        }
        if (list.Count != id_arr.Length)
        {
            return new
            {
                code = "failed",
                msg = "有部分数据集资料未查到"
            };
        }
        foreach (dynamic item in list)
        {
            if (!BoolStd.IsNotBoolThen(item.IsActive))
            {
                return new
                {
                    code = "failed",
                    msg = $"数据集“{item.Title}”未启用，停止执行"
                };
            }
        }
        FrameDLRObject data = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
        var tasklist = new List<Task<object>>();
        foreach (dynamic info in list)
        {
            var parameters = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET_PARAMETERS", "a")
                              where t.SetUID == info.SetUID
                              select t).GetQueryList(metaup).Select(d => ComFunc.nvl(d.GetValue("Express"))).ToList();
            var pexpress = BIParametersExpress.Parse(parameters);
            string biexpress = ComFunc.nvl(info.BIExpress);
            string other_filter_str = other_filters.Keys.Contains(info.Title) ? ComFunc.nvl(other_filters.GetValue(info.Title)) : "";
            var re = BIExpress.Parse(biexpress, other_filter_str, GetBIParameters(pexpress.Result, metaup));
            if (!re.IsSuccess)
            {
                return new
                {
                    code = "failed",
                    msg = re.Msg
                };
            }
            EFFC.Frame.Net.Unit.DB.Datas.UnitDataCollection uc = ExcuteBIExpress(re.Result, metaup, ComFunc.nvl(info.SourceUID));
            var tdata = FrameDLRObject.CreateInstance(ResultHelper.DFormQueryByPageFormat(uc, include_sql_info), FrameDLRFlags.SensitiveCase).data;
            data.SetValue(info.Title, tdata);
        }

        return new
        {
            code = "success",
            msg = "",
            data
        };
    }
    [EWRARoute("get", "/data_set/{id}/xyz")]
    [EWRARouteDesc("获取指定数据集的维度和量度")]
    [EWRAAddInput("id", "string", "资料UID", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, true)]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
data:{
dimension:'维度对象，array',
measurement:'量度对象，array'
}
}")]
    public object GetXYZ(string id)
    {
        SetCacheEnable(false);
        var metaup = DB.NewMetaUnitParameter();
        dynamic info = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET", "a")
                        where t.SetUID == id || t.title == id
                        select t).GetQueryList(metaup).FirstOrDefault();
        if (info == null)
        {
            return new
            {
                code = "failed",
                msg = "无该资料"
            };
        }
        var parameters = (from t in DB.LamdaTable(metaup, "EXTEND_BI_DATASET_PARAMETERS", "a")
                          where t.SetUID == info.SetUID
                          select t).GetQueryList(metaup).Select(d => ComFunc.nvl(d.GetValue("Express"))).ToList();
        var pexpress = BIParametersExpress.Parse(parameters);
        string biexpress = ComFunc.nvl(info.BIExpress);
        var re = BIExpress.Parse(biexpress, null, GetBIParameters(pexpress.Result, metaup));
        if (!re.IsSuccess)
        {
            return new
            {
                code = "failed",
                msg = re.Msg
            };
        }

        return new
        {
            code = "success",
            msg = "",
            data = new
            {
                dimension = (from t in re.Result.Dimension
                             select new
                             {
                                 key = t.Key,
                                 express = t.Express,
                                 title = t.Title
                             }).ToArray(),
                measurement = (from t in re.Result.Measurement
                               select new
                               {
                                   key = t.Key,
                                   express = t.Express,
                                   title = t.Title
                               }).ToArray()
            }
        };
    }

    Dictionary<string, object> getContext()
    {
        var where_context = new Dictionary<string, object>();
        where_context.Add("__now_date__", DateTime.Now.ToString("yyyy-MM-dd"));
        where_context.Add("__now__", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        where_context.Add("__login_id__", TokenPayLoad.ID);
        where_context.Add("__login_name__", TokenPayLoad["name"]);
        where_context.Add("__user_no__", TokenPayLoad["userno"]);
        where_context.Add("__user_name__", TokenPayLoad["username"]);
        where_context.Add("__user_type__", TokenPayLoad["usertype"]);
        where_context.Add("__role_no__", TokenPayLoad["roleno"]);
        where_context.Add("__role_name__", TokenPayLoad["rolename"]);
        where_context.Add("__no__", TokenPayLoad["no"]);

        return where_context;
    }
    FrameDLRObject parseFixedExpress(string json)
    {
        var where_context = getContext();

        try
        {
            FrameDLRObject rtn = FrameDLRObject.CreateInstance(json, FrameDLRFlags.SensitiveCase, where_context.ToArray());
            return rtn;
        }
        catch (Exception ex)
        {
            return null;
        }
    }
    EFFC.Frame.Net.Unit.DB.Datas.UnitDataCollection ExcuteBIExpress(BIExpress expr, UnitParameter metaup, string sourceuid)
    {
        if (string.IsNullOrEmpty(sourceuid))
        {
            var up = DB.NewDBUnitParameter();
            var re = DB.Excute(up, expr.ToDBExpress(), true);
            return re;
        }
        else
        {
            var ds = DataSourceUtilities.GetSource(metaup, sourceuid);

            var up = ds.GetSourceUnitParameter(this);
            var re = DB.Excute(up, expr.ToDBExpress(), true);
            return re;
        }
    }

    bool TestExpress(BIExpress expr, UnitParameter metaup, string sourceuid, ref string msg)
    {
        if (string.IsNullOrEmpty(sourceuid))
        {
            var up = DB.NewDBUnitParameter();
            try
            {
                up.Count_Of_OnePage = 1;
                var re = DB.Excute(up, expr.ToDBExpress());
            }
            catch (Exception ex)
            {
                msg = ex.Message;
                return false;
            }
        }
        else
        {
            var ds = DataSourceUtilities.GetSource(metaup, sourceuid);
            if (ds == null)
            {
                msg = "测试失败:数据源不存在";
                return false;
            }

            var up = ds.GetSourceUnitParameter(this);
            try
            {
                up.Count_Of_OnePage = 1;
                var re = DB.Excute(up, expr.ToDBExpress());
            }
            catch (Exception ex)
            {
                msg = ex.Message;
                return false;
            }
        }

        return true;
    }
    Dictionary<string, object> GetBIParameters(BIParametersExpress p, UnitParameter metaup)
    {
        var rtn = getContext();
        if (p == null) return rtn;
        foreach (var param in p.Parameters)
        {
            rtn.Add(param.ParameterName, GetParameterValue(param, metaup));
        }
        return rtn;
    }
    object GetParameterValue(BIParametersExpress.BIParameter expr, UnitParameter metaup)
    {
        if (expr.DataSource == "_meta_")
        {
            var up = DB.NewDBUnitParameter();
            var re = DB.Excute(up, expr.ToDBExpress(), true).QueryData<FrameDLRObject>();
            if (expr.Action != "array" && expr.Action != "")
            {
                if (re.FirstOrDefault() == null)
                {
                    if (expr.Action.EndsWith("_zero")
                        || expr.Action == "count")
                    {
                        return 0;
                    }
                    else
                    {
                        return null;
                    }
                }
                else
                {
                    if (expr.Action.EndsWith("_zero")
                       || expr.Action == "count")
                    {
                        return FormatDBValue4Query(re.FirstOrDefault().GetValue(expr.ParameterName), 0);
                    }
                    else
                    {
                        return FormatDBValue4Query(re.FirstOrDefault().GetValue(expr.ParameterName));
                    }
                }
            }
            else
            {
                return re.ToList<object>().Select(d =>
                {
                    var dobj = (FrameDLRObject)d;
                    return FormatDBValue4Query(dobj.GetValue(expr.ParameterName));
                }).ToList();
            }
        }
        else
        {
            var ds = DataSourceUtilities.GetSource(metaup, expr.DataSource);

            var up = ds.GetSourceUnitParameter(this);
            var re = DB.Excute(up, expr.ToDBExpress()).QueryData<FrameDLRObject>();
            if (expr.Action != "array" && expr.Action != "")
            {
                if (re.FirstOrDefault() == null)
                {
                    if (expr.Action.EndsWith("_zero")
                        || expr.Action == "count")
                    {
                        return 0;
                    }
                    else
                    {
                        return null;
                    }
                }
                else
                {
                    if (expr.Action.EndsWith("_zero")
                        || expr.Action == "count")
                    {
                        return FormatDBValue4Query(re.FirstOrDefault().GetValue(expr.ParameterName), 0);
                    }
                    else
                    {
                        return FormatDBValue4Query(re.FirstOrDefault().GetValue(expr.ParameterName));
                    }
                }
            }
            else
            {
                return re.ToList<object>().Select(d =>
                {
                    var dobj = (FrameDLRObject)d;
                    return FormatDBValue4Query(dobj.GetValue(expr.ParameterName));
                }).ToList<object>();
            }
        }
    }
    bool TestParameterExpress(BIParametersExpress.BIParameter expr, UnitParameter metaup, ref string msg)
    {
        if (expr.DataSource == "_meta_")
        {
            var up = DB.NewDBUnitParameter();
            try
            {
                up.Count_Of_OnePage = 1;
                var re = DB.Excute(up, expr.ToDBExpress());
            }
            catch (Exception ex)
            {
                msg = ex.Message;
                return false;
            }
        }
        else
        {
            var ds = DataSourceUtilities.GetSource(metaup, expr.DataSource);
            if (ds == null)
            {
                msg = "测试失败:数据源不存在";
                return false;
            }

            var up = ds.GetSourceUnitParameter(this);
            try
            {
                up.Count_Of_OnePage = 1;
                var re = DB.Excute(up, expr.ToDBExpress());
            }
            catch (Exception ex)
            {
                msg = ex.Message;
                return false;
            }
        }

        return true;
    }
    private object FormatDBValue4Query(object v, object default_val_if_null = null)
    {
        if (v == null) return default_val_if_null;
        if (v is DateTime)
        {
            return ((DateTime)v).ToString("yyyy-MM-dd HH:mm:ss");
        }
        else if (v is bool)
        {
            return BoolStd.ConvertTo(v, 1, 0);
        }
        else
        {
            return v;
        }
    }

}
}
